﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Xml.Linq;
using System.Windows.Forms;
using GuavaData;
using System.Data.SqlClient;
using MySql.Data;
using MySql.Data.MySqlClient;
using System.Data.OleDb;
using System.Data.OracleClient;
using Npgsql;

namespace MultiClassDBA.ChannelBuilder
{
    public partial class ChannelBuilderMainWindow : Form
    {
        GuavaData.Schema initialSchema;
        GuavaData.Channel channel;
        List<GuavaData.Schema> schemaHistory;
        int currentlyDisplayedSchRev;
        List<ChannelGraphNode> channelGraph;

        public static String MSSQL_PROVIDER = "MSSQL";
        public static String MYSQL_PROVIDER = "MySQL";
        public static String ACCESS_PROVIDER = "Access";
        public static String ORACLE_PROVIDER = "Oracle";
        public static String POSTGRES_PROVIDER = "Postgres";

        String password;
        String username;
        String database;
        String server;
        String provider;
       

        public ChannelBuilderMainWindow()
        {
            List<String> mask = new List<String>();
            mask.Add("NAME");
            mask.Add("AGE");
            mask.Add("END");
            MaskParser mp = new MaskParser(mask);
            System.Console.WriteLine(mp.fitsMask("NAME Gabe AGE 18 END"));
            foreach (String s in mp.parse("NAME Gabe AGE 18 END"))
                System.Console.WriteLine(s);

            InitializeComponent();
            channelGraph = new List<ChannelGraphNode>();
            schemaHistory = new List<GuavaData.Schema>();
            initialSchema = new GuavaData.Schema();
            channel = new GuavaData.Channel();
            NodeDetailsTreeView.Nodes.Add(new TreeNode("No Table or Column Selected"));
            this.transformEditor.TabPages.Remove(AuditPage);
            this.transformEditor.TabPages.Remove(AdornPage);
            this.transformEditor.TabPages.Remove(ApplyPage);
        }


        //            Buttons and controls part of the main window

        private void exportXmlChannelButton_Click(object sender, EventArgs e)
        {
            //Save File Dialog
            saveFileDialog1.ShowDialog();
            String path = saveFileDialog1.FileName;
            if (path != null && path != "")
            {
                XDocument x = channel.ToXDocument();
                x.Root.Add(new XElement("initialSchema", schemaHistory[0].GetHashCode()));
                x.Save(path);
            }
        }

        private void ImportChannelButton_Click(object sender, EventArgs e)
        {
            //MessageBox.Show("The schema that this channel was built from must be loaded before trying to load the channel.");
            openFileDialog1.ShowDialog();
            if (openFileDialog1.FileName == "")
                return;
            XDocument channelDoc = XDocument.Load(openFileDialog1.FileName);
            int hash = -1;
            foreach (XElement xe in channelDoc.Element("Channel").Elements())
            {
                if (xe.Name.LocalName == "initialSchema")
                {
                    hash = Convert.ToInt32(xe.Value);
                    xe.Remove();
                }

            }
            int csHashCode = schemaHistory[0].GetHashCode();
            if( csHashCode != hash)
            {
                DialogResult result1 = MessageBox.Show("Channel Builder has determined that you are loading a channel that was built\r\n" +
                    "from a different starting schema. Continuing will likely cause errors. Continue?",
                "WCaution",
                MessageBoxButtons.YesNo);
                if(result1.Equals(DialogResult.No))
                return;
            }
            
            channel = Channel.FromXDocument(channelDoc);
            Channel temp = Channel.FromXDocument(channelDoc);
            List<Schema> l = new List<Schema>();
            while (!(temp.root is Provider))
            {
                temp = Channel.FromXDocument(temp.ToXDocument());
                Transaction t = schemaHistory[0].Transaction;
                temp.PoseTransactionWithEmptyProvider(t);
                l.Add(Schema.SchemaFromGuavaTransaction(t));
                temp.RemoveLastTransform();
            }
            l.Add(schemaHistory[0]);
            l.Reverse();
            l.RemoveAt(l.Count - 1);
            schemaHistory = l;
            channelModified();
        }

        private void schemaRevHistoryComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            displaySchema(schemaHistory[schemaRevHistoryComboBox.SelectedIndex]);
            currentlyDisplayedSchRev = schemaRevHistoryComboBox.SelectedIndex;

        }

        private void loadSchemaButton_Click(object sender, EventArgs e)
        {
            //if(System.IO.File.Exists(@"\\khensu\Home05\buckmasg\Desktop\TestGTree.xml"))
            //    openFileDialog1.FileName = @"\\khensu\Home05\buckmasg\Desktop\TestGTree.xml";
            //else
                openFileDialog1.ShowDialog();
            if (openFileDialog1.FileName == "")
                return;

            channel = new GuavaData.Channel();
            schemaHistory = new List<Schema>();
            testDataResultTextBox.Text = "";
            testDataTableComboBox.Text = "";

            if (openFileDialog1.FileName.EndsWith(".xml") || openFileDialog1.FileName.EndsWith(".XML"))
            {
                initialSchema = GuavaData.Schema.SchemaFromGTree(openFileDialog1.FileName);
                schemaHistory.Add(initialSchema);
                
            }

            schemaRevHistoryComboBox.Items.Add("Input Schema");
            schemaRevHistoryComboBox.Text = "Input Schema";
            loadSchemaButton.Enabled = false;
            schFromDbButton.Enabled = false;
            transformEditor.Enabled = true;
            exportXmlChannelButton.Enabled = true;
            ImportChannelButton.Enabled = true;
            viewChannelButton.Enabled = true;
            removeXfrmButton.Enabled = true;
            expGtree.Enabled = true;

            SendTestDataButton.Enabled = true;
            testDataTableComboBox.Enabled = true;
            SchemaTreeView.Nodes.Clear();
            foreach (Scheme s in schemaHistory[currentlyDisplayedSchRev].tables)
                testDataTableComboBox.Items.Add(s.tableName);
            foreach (TreeNode tn in initialSchema.SchemaToTreeView(false))
                if(!SchemaTreeView.Nodes.Contains(tn))
                    SchemaTreeView.Nodes.Add(tn);
            SchemaTreeView.ExpandAll();
            updateTransformEditor();
        }

        private void ExpandAllCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            if (ExpandAllCheckBox.Checked)
                SchemaTreeView.ExpandAll();
            else
                SchemaTreeView.CollapseAll();
        }

        private void listViewCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            if (schemaHistory.Count != 0) 
                displaySchema(schemaHistory[currentlyDisplayedSchRev]);
        }

        private void SchemaTreeView_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (SchemaTreeView.SelectedNode == null)
                return;
            GuavaData.Schema cs = schemaHistory[currentlyDisplayedSchRev];
            string tableName = SchemaTreeView.SelectedNode.Text;
            Scheme t = cs.getScheme(tableName);
            if (t == null)
                return;
            VPartition_TableComboBox.Text = t.TableName;
            VMerge_Table1ComboBox.Text = t.TableName;
            HPartition_TableComboBox.Text = t.TableName;
            Audit_TableComboBox.Text = t.tableName;
            Pivot_TableComboBox.Text = t.tableName;
            Unpivot_TableComboBox.Text = t.tableName;
            testDataTableComboBox.Text = t.tableName;
                
            TreeNode tn = t.getDetailsTreeNode();
            tn.Expand();
            NodeDetailsTreeView.Nodes.Clear();
            NodeDetailsTreeView.Nodes.Add(tn);
        }

        private void transformEditor_SelectedIndexChanged(object sender, EventArgs e)
        {
            //updateTransformEditor();
        }

        private void SendTestDataButton_Click(object sender, EventArgs e)
        {
            DataTable dt = ((DataTable)TestDataGridView.DataSource);
            if (dt == null)
                return;
            dt.AcceptChanges();
            Transaction t = new Transaction();
            List<String> columnStrings = new List<String>();
            foreach (Object a in dt.Columns)
                columnStrings.Add(((DataColumn)a).ColumnName);
            foreach (DataRow dr in dt.Rows)
            {
                RowConstant rc = new RowConstant();
                for (int i = 0; i < dr.ItemArray.Count(); i++)
                {
                    Object o = dr.ItemArray[i];
                    rc.AddValue(dt.Columns[i].ToString(), new GuavaData.Domain.String(), o);


                }
                t.Add(new Command(new Insert(testDataTableComboBox.Text, columnStrings, rc)));

            }
            channel.GetSQL(t);
            testDataResultTextBox.AppendText(
                "------------------------------------------------------------------------" +
                "--------------------------------------------------------------\r\n");
            if(t.sqlTextResult != null)
                testDataResultTextBox.AppendText(t.sqlTextResult);

        }

        private void SchemaTreeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if (currentlyDisplayedSchRev != 0)
                return;
            TreeNode clickedNode = e.Node;
            if (e.Button == MouseButtons.Right)
                new TableEditor(schemaHistory, clickedNode.Text, this).ShowDialog();
        }

        private void removeXfrmButton_Click(object sender, EventArgs e)
        {
            if (channel.root is Provider)
            {
                MessageBox.Show("The channel is already empty.");
                return;
            }
            channelGraph.RemoveAt(channelGraph.Count - 1);
            schemaHistory.RemoveAt(schemaHistory.Count - 1);
            currentlyDisplayedSchRev = schemaHistory.Count - 1;
            schemaRevHistoryComboBox.SelectedIndex = schemaHistory.Count - 1;
            schemaRevHistoryComboBox.Items.RemoveAt(schemaRevHistoryComboBox.Items.Count - 1);
            channel.RemoveLastTransform();
            channelModified();

            currentlyDisplayedSchRev--;
            schemaRevHistoryComboBox.SelectedIndex--;
            schemaRevHistoryComboBox.Items.RemoveAt(schemaRevHistoryComboBox.Items.Count - 1);
            schemaHistory.RemoveAt(schemaHistory.Count - 1);
        }

        private void viewChannelButton_Click(object sender, EventArgs e)
        {
            new ChannelViewer(channelGraph).Show();
        }

        private void schFromDbButton_Click(object sender, EventArgs e)
        {

            DatabaseInfoForm f = new DatabaseInfoForm();
            f.ShowDialog();

            //if (!f.isComplete())
            // return;

            // strip any semicolons so that the user can't mess with the connection string, still not the right way to do this...
            server = f.getHost().Replace(";", "");
            database = f.getDatabase().Replace(";", "");
            username = f.getUsername().Replace(";", "");
            password = f.getPassword().Replace(";", "");

            // provider is MS SQL by default
            if (f.GetProvider() == MSSQL_PROVIDER)
            {
                provider = MSSQL_PROVIDER;
                DBConnection.Provider = MSSQL_PROVIDER;
                SqlProvider.Provider = MSSQL_PROVIDER;
                if (server.Equals(""))
                {
                    server = "VuTran-PC";
                    database = "ChannelDB";
                    username = "sa";
                    password = "123";
                }
            }
            else if (f.GetProvider() == MYSQL_PROVIDER)
            {
                provider = MYSQL_PROVIDER;
                DBConnection.Provider = MYSQL_PROVIDER;
                SqlProvider.Provider = MYSQL_PROVIDER;
                if (server.Equals(""))
                {
                    server = "localhost";
                    database = "channel_db";
                    username = "root";
                    password = "123456";
                }
            }
            else if (f.GetProvider() == ACCESS_PROVIDER)
            {
                provider = ACCESS_PROVIDER;
                DBConnection.Provider = ACCESS_PROVIDER;
                SqlProvider.Provider = ACCESS_PROVIDER;
                if (server.Equals(""))
                {
                    database = "F:\\DrLois\\GuaveProject\\GuavaMain\\Resources\\tele.mdb";
                }
            }
            else if (f.GetProvider() == ORACLE_PROVIDER)
            {
                provider = ORACLE_PROVIDER;
                DBConnection.Provider = ORACLE_PROVIDER;
                SqlProvider.Provider = ORACLE_PROVIDER;
                SqlText.IsOracle = true;
                PivotOp.IsOracle = true;
                Pivot.IsOracle = true;

                if (server.Equals(""))
                {
                    database = "(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)" +
                         "(HOST=localhost)(PORT=1521))(CONNECT_DATA=" +
                         "(SERVICE_NAME=XE)))";
                    username = "sa";
                    password = "123";
                }
            }
            else
            {
                provider = POSTGRES_PROVIDER;
                DBConnection.Provider = POSTGRES_PROVIDER;
                SqlProvider.Provider = POSTGRES_PROVIDER;
                SqlText.IsPostgres = true;
                if (server.Equals(""))
                {
                    server = "localhost";
                    database = "channel_db";
                    username = "postgres";
                    password = "123";
                }
            }

            if (provider == MSSQL_PROVIDER)
            {
                System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection
                    ("Data Source=" + server + ";initial catalog=" + database + ";Integrated security=false;User ID=" +
                    username + ";Password=" + password);
                try
                {
                    conn.Open();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Could not open connection to server. \r\n\r\n" + ex.Message);
                    return;
                }

                try
                {
                    schemaHistory.Add(Schema.QuerySchemaFromDB(conn));
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error constructing schema from database query. \r\n\r\n" + ex.Message);
                    conn.Close();
                }
                conn.Close();
            }
            else if (provider == MYSQL_PROVIDER)
            {
                string connStr = "server=" + server + ";database=" + database + ";user=" +
                    username + ";password=" + password;
                MySqlConnection conn = new MySqlConnection(connStr);
                try
                {
                    conn.Open();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Could not open connection to server. \r\n\r\n" + ex.Message);
                    return;
                }

                try
                {
                    schemaHistory.Add(Schema.QuerySchemaFromDB(conn));
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error constructing schema from database query. \r\n\r\n" + ex.Message);
                    conn.Close();
                }
                conn.Close();
            }
            else if (provider == ACCESS_PROVIDER)
            {
                OleDbConnection conn = new OleDbConnection(
                     @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + database + @";Persist Security Info=False;");
                try
                {
                    conn.Open();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Could not open connection to server. \r\n\r\n" + ex.Message);
                    return;
                }

                try
                {
                    schemaHistory.Add(Schema.QuerySchemaFromDB(conn));
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error constructing schema from database query. \r\n\r\n" + ex.Message);
                    conn.Close();
                }
                conn.Close();
            }
            else if (provider == ORACLE_PROVIDER)
            {
                OracleConnectionStringBuilder str = new OracleConnectionStringBuilder();
                str.DataSource = "(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)" +
                         "(HOST=localhost)(PORT=1521))(CONNECT_DATA=" +
                         "(SERVICE_NAME=XE)))";
                str.UserID = username;
                str.Password = password;
                OracleConnection conn = new OracleConnection(str.ToString());
                try
                {
                    conn.Open();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Could not open connection to server. \r\n\r\n" + ex.Message);
                    return;
                }

                try
                {
                    schemaHistory.Add(Schema.QuerySchemaFromDB(conn, username));
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error constructing schema from database query. \r\n\r\n" + ex.Message);
                    conn.Close();
                }
                conn.Close();
            }
            else if (provider == POSTGRES_PROVIDER)
            {
                String strConn = "Server=" + server + ";Port=5432;User Id=" + username + ";Password=" 
                                + password + ";Database=" + database + ";";
                NpgsqlConnection conn = new NpgsqlConnection(strConn);

                try
                {
                    conn.Open();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Could not open connection to server. \r\n\r\n" + ex.Message);
                    return;
                }

                try
                {
                    schemaHistory.Add(Schema.QuerySchemaFromDB(conn));
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error constructing schema from database query. \r\n\r\n" + ex.Message);
                    conn.Close();
                }
                conn.Close();
            }

            exportXmlChannelButton.Enabled = true;
            ImportChannelButton.Enabled = true;
            viewChannelButton.Enabled = true;
            removeXfrmButton.Enabled = true;

            initialSchema = schemaHistory[0];
            schemaRevHistoryComboBox.Items.Add("Input Schema");
            schemaRevHistoryComboBox.Text = "Input Schema";
            transformEditor.Enabled = true;
            SchemaTreeView.Nodes.Clear();
            foreach (TreeNode tn in schemaHistory[0].SchemaToTreeView(false))
                if (!SchemaTreeView.Nodes.Contains(tn))
                    SchemaTreeView.Nodes.Add(tn);
            SchemaTreeView.ExpandAll();
            getTestDataButton.Enabled = true;
            numResultsTextBox.Enabled = true;
            testDataTableComboBox.Enabled = true;
            expGtree.Enabled = true;
            loadSchemaButton.Enabled = false;
            schFromDbButton.Enabled = false;
            updateTransformEditor();

            
        }

        private void getTestDataButton_Click(object sender, EventArgs e)
        {
            //Connect to database and return top 10 rows from the given table
            //Ex: SELECT TOP 10 * FROM COL
            if (schemaHistory.Count == 0)
                return;
            Schema cs = schemaHistory[schemaHistory.Count - 1];
            String tableName = testDataTableComboBox.Text;
            if (cs.getScheme(tableName) == null)
            {
                MessageBox.Show("Could not find table " + tableName + ".");
                return;
            }
            System.Console.WriteLine("Server: " + server);
            System.Console.WriteLine("Database: " + database);
            DBConnection.Initialize(server, database, username, password);
            TableRef tref = new TableRef(tableName, "D_0");
            List<String> cnames = new List<String>();
            foreach (Column c in cs.getScheme(tableName).columns)
            {
                tref.AddColumn(c.Name, c.Name, c.dom);
                cnames.Add(c.Name);
            }


            Project proj = new Project(tref, cnames);


            Transaction t = new Transaction(proj);
            Channel temp = channel;
            channel = Channel.InvertChannel(channel);

            try
            {
                Transaction test = cs.Transaction;
                channel.PoseTransactionWithEmptyProvider(test);
                String q = channel.GetSQL(t);
                channel = temp;
                if (provider == MSSQL_PROVIDER)
                {
                    int splitIndex = q.IndexOf("SELECT ") + 7;
                    q = q.Substring(0, splitIndex) + " TOP " + numResultsTextBox.Text + " " + q.Substring(splitIndex, q.Length - splitIndex);
                }
                else if (provider == MYSQL_PROVIDER)
                {
                    q = q.Replace("[", "").Replace("]", "");
                    q = q + "LIMIT 0, " + numResultsTextBox.Text;
                }
                else if (provider == ACCESS_PROVIDER)
                {
                    q = "SELECT TOP " + numResultsTextBox.Text + " * FROM (" + q + ")";
                }
                else if (provider == ORACLE_PROVIDER)
                {
                    q = q.Replace("[", "\"").Replace("]", "\"");
                    if (q.IndexOf("WHERE") < 0)
                        q = q + " WHERE ROWNUM < " + numResultsTextBox.Text;
                    // how to limit with nested queries?    
                }
                else if (provider == POSTGRES_PROVIDER)
                {
                    q = q.ToLower();
                    q = q + "LIMIT " + numResultsTextBox.Text;
                }
                
                DataSet ds = DBConnection.ExecuteQuery(q);
                DataTable dt = ds.Tables[0];

                TestDataGridView.DataSource = dt;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error getting test data: \r\n\r\n" + ex.Message);
                //throw ex;//use for debugging
            }
        }

        private void testDataTableComboBox_TextChanged(object sender, EventArgs e)
        {
            String tableName = testDataTableComboBox.Text;
            if (schemaHistory.Count == 0)
                return;
            Schema cs = cs = schemaHistory[currentlyDisplayedSchRev];
            if (getTestDataButton.Enabled)//If we're going from a natural schema to a DB, we only want to be able to select from tables in the initial schema
                cs = schemaHistory[0];

            Scheme s = null;
            s = cs.getScheme(tableName);
            if (s == null)
            {
                TestDataGridView.DataSource = null;
                return;
            }

            DataTable dt = new DataTable();

            foreach (Column c in s.columns)
                if (!dt.Columns.Contains(c.Name)) //Works for now, should probably find out why it tries to add duplicate columns.
                    dt.Columns.Add(c.Name);

            TestDataGridView.DataSource = dt;
        }



        //          Buttons and controls part of a specific transform tab
        private void VPartition_TableComboBox_TextChanged(object sender, EventArgs e)
        {
            GuavaData.Schema cs = schemaHistory[currentlyDisplayedSchRev];
            //Populates the fields that contain columns once a starting table has been selected
            String tableName = VPartition_TableComboBox.Text;
            if (tableName == "")
                return;
            try
            {
                cs.getScheme(tableName);
                VPartition_TableComboBox.BackColor = Color.White;
            }
            catch { return; }
            Scheme table = cs.getScheme(tableName);
            if (table != null)
            {
                VPartition_KeepCols1CheckedListBox.Items.Clear();
                VPartition_KeepCols2CheckedListBox.Items.Clear();
                foreach (GuavaData.Column c in table.columns)
                {
                    VPartition_KeepCols1CheckedListBox.Items.Add(c.Name, CheckState.Checked);
                    VPartition_KeepCols2CheckedListBox.Items.Add(c.Name);

                }
                foreach (GuavaData.Column c in table.pkColumns)
                {
                    VPartition_KeepCols1CheckedListBox.Items.Remove(c.Name);
                    VPartition_KeepCols2CheckedListBox.Items.Remove(c.Name);
                }
                VPartition_t1NameTextBox.Text = tableName;
                VPartition_t2NameTextBox.Text = tableName + "-B";
            }
            else
            {
                if (tableName != "")
                    VPartition_TableComboBox.BackColor = System.Drawing.Color.Yellow;
                else
                    VPartition_TableComboBox.BackColor = System.Drawing.Color.White;
            }
        }

        private void VPartition_KeepCols1CheckedListBox_MouseUp(object sender, MouseEventArgs e)
        {
            String tableName = VPartition_TableComboBox.Text;
            GuavaData.Scheme table = schemaHistory[schemaHistory.Count - 1].getScheme(tableName);
            if (table != null)
            {
                VPartition_KeepCols2CheckedListBox.Items.Clear();
                foreach (String s in VPartition_KeepCols1CheckedListBox.Items)
                {
                    if (VPartition_KeepCols1CheckedListBox.CheckedItems.Contains(s))
                        VPartition_KeepCols2CheckedListBox.Items.Add(s, CheckState.Unchecked);
                    else
                        VPartition_KeepCols2CheckedListBox.Items.Add(s, CheckState.Checked);
                }
            }
        }

        private void VPartition_KeepCols2CheckedListBox_MouseUp(object sender, MouseEventArgs e)
        {
            String tableName = VPartition_TableComboBox.Text;
            GuavaData.Scheme table = schemaHistory[schemaHistory.Count - 1].getScheme(tableName);
            if (table != null)
            {
                VPartition_KeepCols1CheckedListBox.Items.Clear();
                foreach (String s in VPartition_KeepCols2CheckedListBox.Items)
                {
                    if (VPartition_KeepCols2CheckedListBox.CheckedItems.Contains(s))
                        VPartition_KeepCols1CheckedListBox.Items.Add(s, CheckState.Unchecked);
                    else
                        VPartition_KeepCols1CheckedListBox.Items.Add(s, CheckState.Checked);
                }
            }
        }

        private void VPartition_AddToChannelButton_Click(object sender, EventArgs e)
        {
            //add VPartition to channel
            List<String> columns = new List<String>();
            foreach (String s in VPartition_KeepCols1CheckedListBox.CheckedItems)
                columns.Add(s);
            if (VPartition_KeepCols1CheckedListBox.CheckedItems.Count == 0 || VPartition_KeepCols2CheckedListBox.CheckedItems.Count == 0)
            {
                MessageBox.Show("Must select some columns to split");
                return;
            }
            if (VPartition_t2NameTextBox.Text == "")
            {
                MessageBox.Show("Table name cannot be blank");
                return;
            }
            if (schemaHistory[schemaHistory.Count -1].getScheme(VPartition_t2NameTextBox.Text) != null)
            {
                MessageBox.Show("A table with the name " + VPartition_t2NameTextBox.Text + " already exists in the current schema.");
                return;
            }
            String inTable = VPartition_TableComboBox.Text;
            String outTable = VPartition_t2NameTextBox.Text;

            channel.AddToEnd(new GuavaData.VSplit(inTable,outTable,columns));
            if (channelModified())
            {
                ChannelGraphNode n = new ChannelGraphNode("VPartition");
                n.inTableRev = schemaHistory.Count - 1;
                n.outTableRev = schemaHistory.Count;
                n.inTables.Add(inTable);
                n.outTables.Add(inTable);
                n.outTables.Add(outTable);
                channelGraph.Add(n);
            }

            
        }

        private void VMerge_Table1ComboBox_TextChanged(object sender, EventArgs e)
        {
            GuavaData.Schema cs = schemaHistory[schemaHistory.Count - 1];

            GuavaData.Scheme t = cs.getScheme(VMerge_Table1ComboBox.Text);
            if (t != null)
            {
                VMerge_Table1ComboBox.BackColor = System.Drawing.Color.White;
                VMerge_Table2ComboBox.Enabled = true;
                VMerge_Table2ComboBox.Items.Clear();
                bool oneToOne = true;
                foreach (Column c in t.pkColumns)
                    if (!t.fkColumns.Contains(c))
                        oneToOne = false;
                foreach (Column c in t.fkColumns)
                    if (!t.pkColumns.Contains(c))
                        oneToOne = false;
                if (oneToOne)
                    foreach (Scheme s in t.parents)
                        VMerge_Table2ComboBox.Items.Add(s.TableName);
                foreach (String str in t.children)
                {
                    Scheme s = cs.getScheme(str);
                    oneToOne = true;
                    foreach (Column c in s.pkColumns)
                        if (!s.fkColumns.Contains(c))
                            oneToOne = false;
                    foreach (Column c in s.fkColumns)
                        if (!s.pkColumns.Contains(c))
                            oneToOne = false;
                    if (oneToOne)
                        VMerge_Table2ComboBox.Items.Add(s.TableName);
                }
                VMerge_resultTableNameTextBox.Text = VMerge_Table1ComboBox.Text;
            }
            else
            {
                VMerge_Table1ComboBox.BackColor = System.Drawing.Color.Yellow;
                VMerge_Table2ComboBox.Enabled = false;
                if (VMerge_Table1ComboBox.Text == "")
                    VMerge_Table1ComboBox.BackColor = System.Drawing.Color.White;
            }
        }

        private void VMerge_Table2ComboBox_TextChanged(object sender, EventArgs e)
        {
        }

        private void VMerge_AddToChannelButton_Click(object sender, EventArgs e)
        {
            


            //Adds a new VMerge to the channel
            GuavaData.Schema cs = schemaHistory[schemaHistory.Count - 1];
            GuavaData.Scheme t1 = cs.getScheme(VMerge_Table1ComboBox.Text);
            GuavaData.Scheme t2 = cs.getScheme(VMerge_Table2ComboBox.Text);

            //Validate forms data
            if (t1 == null || t2 == null)
                return;
            if (VMerge_resultTableNameTextBox.Text == "")
            {
                MessageBox.Show("Result table name must not be blank.");
                return;
            }

            if (t1.parents.Contains(t2))
            {
                Scheme temp = t1;
                t1 = t2;
                t2 = temp;
            }

            GuavaData.Transform t = new GuavaData.VMerge(t1.tableName, t2.tableName);
            channel.AddToEnd(t);
            if (channelModified())
            {
                ChannelGraphNode n = new ChannelGraphNode("VMerge");
                n.inTableRev = schemaHistory.Count - 1;
                n.inTables.Add(t1.tableName);
                n.inTables.Add(t2.tableName);
                n.outTableRev = schemaHistory.Count;
                n.outTables.Add(t1.tableName);
                channelGraph.Add(n);
            }
            
        }

        private void HPartition_TableComboBox_TextChanged(object sender, EventArgs e)
        {
            GuavaData.Schema currentSchema = schemaHistory[currentlyDisplayedSchRev];
            try
            {
                GuavaData.Scheme t = currentSchema.getScheme(HPartition_TableComboBox.Text);
                HPartition_BaseColumnComboBox.Items.Clear();
                foreach (GuavaData.Column column in t.columns)
                    if (column != null)
                        HPartition_BaseColumnComboBox.Items.Add(column.Name);
            }
            catch
            {
                HPartition_BaseColumnComboBox.Items.Clear();
            }
            
        }

        private void HPartition_BaseColumnComboBox_TextChanged(object sender, EventArgs e)
        {
            HPartition_BaseColValuesListBox.Items.Clear();
            try
            {
                Schema s = schemaHistory[currentlyDisplayedSchRev];
                Scheme scheme = s.getScheme(HPartition_TableComboBox.Text);
                foreach (Column c in scheme.columns)
                {
                    if (c.Name == HPartition_BaseColumnComboBox.Text && c.dom is GuavaData.Domain.Enumerated)
                    {

                        HPartition_BaseColumnComboBox.BackColor = Color.White;
                        foreach (String str in ((GuavaData.Domain.Enumerated)c.dom).Items)
                            HPartition_BaseColValuesListBox.Items.Add(str);
                    }

                }

            }
            catch
            {
                HPartition_BaseColumnComboBox.BackColor = Color.Yellow;
            }
            if (HPartition_BaseColumnComboBox.Text == "")
            {
                HPartition_BaseColumnComboBox.BackColor = Color.White;
            }
        }

        private void HPartition_AddToChannelButton_Click(object sender, EventArgs e)
        {
            String tableName = HPartition_TableComboBox.Text;
            String column = HPartition_BaseColumnComboBox.Text;

            //Validate Data Fields
            GuavaData.Schema cs = schemaHistory[schemaHistory.Count - 1];
            GuavaData.Scheme table = cs.getScheme(tableName);
            if (table == null)
                return;
            /*
            if (!table.columns.Contains(new GuavaData.Column(column, new GuavaData.Domain.)))
                return;
             * */
            if (HPartition_BaseColValuesListBox.Items.Count == 0)
            //return; 
            {
                try
                {
                    Scheme s = schemaHistory[schemaHistory.Count - 1].getScheme(tableName);
                    Column c = s.getColumn(column);
                    DBConnection.Initialize(server, database, username, password);
                    TableRef tref = new TableRef(s.tableName, "D_0");
                    List<String> cnames = new List<String>();
                    tref.AddColumn(c.Name, c.Name, c.dom);
                    //tref.Columns.Add(c.Name);
                    //tref.exposedColumns.Add(c.Name);
                    //tref.exposedDomains.Add(c.dom);
                    cnames.Add(c.Name);



                    Project proj = new Project(tref, cnames);


                    Transaction tr = new Transaction(proj);
                    Channel temp = channel;
                    channel = Channel.InvertChannel(channel);

                    Transaction test = schemaHistory[schemaHistory.Count - 1].Transaction;
                    channel.PoseTransactionWithEmptyProvider(test);
                    String q = channel.GetSQL(tr);
                    int splitIndex = q.IndexOf("SELECT ") + 7;
                    q = q.Substring(0, splitIndex) + " DISTINCT " + q.Substring(splitIndex, q.Length - splitIndex);
                    channel = temp;

                    DataSet ds = DBConnection.ExecuteQuery(q);
                    DataTable dt = ds.Tables[0];
                    List<String> enumeration = new List<String>();
                    foreach (DataRow dr in dt.Rows)
                    {
                        bool startsWithNumber = false;
                        for (int j = 0; j < 10; j++)
                        {
                            if (dr.ItemArray[0].ToString().StartsWith(j.ToString()))
                                startsWithNumber = true;
                        }
                        String toAdd = "";
                        //if (startsWithNumber)
                        //    toAdd = "c_" + dr.ItemArray[0].ToString();
                        //else
                        toAdd = dr.ItemArray[0].ToString();
                        enumeration.Add(toAdd);
                        HPartition_BaseColValuesListBox.Items.Add(toAdd);
                    }

                    Operator op = tr.Contents[0].root;
                    String tName;
                    while (true)
                    {
                        if (op is Project)
                            op = ((Project)op).Child;
                        if (op is Filter)
                            op = ((Filter)op).Child;
                        if (op is TableRef)
                        {
                            tName = ((TableRef)op).Table;
                            break;
                        }
                        if (op == null)
                            throw new Exception("Error finding original table name");
                    }
                    schemaHistory[0].getScheme(tName).getColumn(c.Name).dom = new GuavaData.Domain.Enumerated(enumeration);
                    initialSchema.getScheme(tName).getColumn(c.Name).dom = new GuavaData.Domain.Enumerated(enumeration);
                }
                catch (Exception ex)
                {
                    System.Console.WriteLine(ex.Message);
                    MessageBox.Show("Error while getting domain enumeration for hsplit");
                    return;
                }
            }
            //Create new HPartition and add it to the channel
            GuavaData.Transform t = new GuavaData.HSplit(tableName, column);
            channel.AddToEnd(t);
            if (channelModified())
            {
                ChannelGraphNode n = new ChannelGraphNode("HPartition");
                n.inTableRev = schemaHistory.Count - 1;
                n.outTableRev = schemaHistory.Count;
                n.inTables.Add(tableName);
                foreach (String s in ((GuavaData.Domain.Enumerated)
                            schemaHistory[schemaHistory.Count -2].getScheme(tableName).getColumn(column).dom).Items)
                    n.outTables.Add(s);
                channelGraph.Add(n);
            }
        }
        

        private void HMerge_AddToChannelButton_Click(object sender, EventArgs e)
        {
            String newColumn = HMerge_ResultColumnNameTextBox.Text;
            HMerge_ResultColumnNameTextBox.Text = "";
            if (newColumn.Equals("")) newColumn = "OriginTable";

            List<String> tableNames = new List<String>();
            foreach (String s in HMerge_ToMergeListBox.CheckedItems)
                tableNames.Add(s);
            String newTableName = HMerge_ResultTableNameTextBox.Text;

            //Validate data fields
            if (newTableName == "")
            {
                MessageBox.Show("New table name must not be blank.");
                return;
            }
            if (schemaHistory[schemaHistory.Count - 1].getScheme(HMerge_ResultTableNameTextBox.Text) != null)
            {
                MessageBox.Show("Table with name " + HMerge_ResultTableNameTextBox.Text + " already exists.");
                return;
            }
            if (tableNames.Count < 2)
            {
                MessageBox.Show("Two or more tables must be selected to merge them.");
                return;
            }
            List<String> columns = new List<String>();
            foreach (Column c in schemaHistory[schemaHistory.Count - 1].getScheme(tableNames[0]).columns)
            {
                columns.Add(c.Name + c.dom.ToString());
            }

            foreach (String s in tableNames)
                for (int i = 0; i < schemaHistory[schemaHistory.Count - 1].getScheme(s).columns.Count; i++)
                {
                    Column c = schemaHistory[schemaHistory.Count - 1].getScheme(s).columns[i];
                    if (!columns[i].Equals(c.Name + c.dom.ToString()))
                    {
                        MessageBox.Show("The selected tables are not compatible: The tables to be merged must have " +
                            "the same columns.");
                        return;
                    }
                }


            GuavaData.Transform t = new GuavaData.HMerge(tableNames, newTableName, newColumn);

            channel.AddToEnd(t);

            if (channelModified())
            {
                ChannelGraphNode n = new ChannelGraphNode("HMerge");
                n.inTableRev = schemaHistory.Count - 1;
                n.outTableRev = schemaHistory.Count;
                n.outTables.Add(newTableName);
                foreach (String s in tableNames)
                    n.inTables.Add(s);
                channelGraph.Add(n);
            }

        }

        private void Pivot_TableComboBox_TextChanged(object sender, EventArgs e)
        {

            Scheme s = schemaHistory[schemaHistory.Count - 1].getScheme(Pivot_TableComboBox.Text);
            if (s == null)
                return;
            Pivot_AttrColComboBox.Items.Clear();
            Pivot_ValueColComboBox.Items.Clear();
            foreach (Column c in s.columns)
            {
                Pivot_AttrColComboBox.Items.Add(c.Name);
                Pivot_ValueColComboBox.Items.Add(c.Name);
            }


        }

        private void Pivot_AddToChannelButton_Click(object sender, EventArgs e)
        {
            try
            {
                Scheme s = schemaHistory[schemaHistory.Count - 1].getScheme(Pivot_TableComboBox.Text);
                Column c = s.getColumn(Pivot_AttrColComboBox.Text);
                if (!(c.dom is GuavaData.Domain.Enumerated))
                {
                    if (SendTestDataButton.Enabled)
                    {
                        MessageBox.Show("Attribute column's domain must be of type Enumerated");
                        return;
                    }
                    MessageBox.Show("Attribute column's domain not of type Enumerated. Will query database for enumeration.");
                    try
                    {

                        DBConnection.Initialize(server, database, username, password);
                        TableRef tref = new TableRef(s.tableName, "D_0");
                        List<String> cnames = new List<String>();
                        tref.AddColumn(c.Name, c.Name, c.dom);
                        //tref.Columns.Add(c.Name);
                        //tref.exposedColumns.Add(c.Name);
                        //tref.exposedDomains.Add(c.dom);
                        cnames.Add(c.Name);

                        Project proj = new Project(tref, cnames);

                        Transaction tr = new Transaction(proj);
                        Channel temp = channel;
                        channel = Channel.InvertChannel(channel);

                        Transaction test = schemaHistory[schemaHistory.Count - 1].Transaction;
                        channel.PoseTransactionWithEmptyProvider(test);
                        String q = channel.GetSQL(tr);
                        int splitIndex = q.IndexOf("SELECT ") + 7;
                        q = q.Substring(0, splitIndex) + " DISTINCT "  + q.Substring(splitIndex, q.Length - splitIndex);
                        channel = temp;

                        DataSet ds = DBConnection.ExecuteQuery(q);
                        DataTable dt = ds.Tables[0];
                        List<String> enumeration = new List<String>();
                        foreach (DataRow dr in dt.Rows)
                        {
                            bool startsWithNumber = false;
                            for (int j = 0; j < 10; j++)
                            {
                                if (dr.ItemArray[0].ToString().StartsWith(j.ToString()))
                                    startsWithNumber = true;
                            }
                            String toAdd = "";
                           // if (startsWithNumber)
                             //   toAdd = "c_" + dr.ItemArray[0].ToString();
                            //else
                                toAdd = dr.ItemArray[0].ToString();
                            enumeration.Add(toAdd);
                        }

                        Operator op = tr.Contents[0].root;
                        String tName;
                        while (true)
                        {
                            if (op is Project)
                                op = ((Project)op).Child;
                            if (op is Filter)
                                op = ((Filter)op).Child;
                            if (op is TableRef)
                            {
                                tName = ((TableRef)op).Table;
                                break;
                            }
                            if (op == null)
                                throw new Exception("Error finding original table name");
                        }
                        schemaHistory[0].getScheme(tName).getColumn(c.Name).dom = new GuavaData.Domain.Enumerated(enumeration);
                        initialSchema.getScheme(tName).getColumn(c.Name).dom = new GuavaData.Domain.Enumerated(enumeration);
                    }
                    catch (Exception ex)
                    {
                        System.Console.WriteLine(ex.Message);
                        MessageBox.Show("Error while getting domain enumeration for pivot");
                        return;
                    }
                }
            }
            catch
            {
                MessageBox.Show("Could not find table \"" + Pivot_TableComboBox.Text + "\" in current schema");
                return;
            }
            List<String> table = new List<String>(1);
            List<String> attr = new List<String>(1);
            List<String> value = new List<String>(1);
            table.Add(Pivot_TableComboBox.Text);
            attr.Add(Pivot_AttrColComboBox.Text);
            value.Add(Pivot_ValueColComboBox.Text);
            Pivot t = new Pivot(table, attr, value);
            channel.AddToEnd(t);
            if (channelModified())
            {
                foreach (String s in table)
                {
                    ChannelGraphNode n = new ChannelGraphNode("Pivot");
                    n.inTableRev = schemaHistory.Count - 1;
                    n.inTables.Add(Pivot_TableComboBox.Text);
                    n.outTableRev = schemaHistory.Count;
                    n.outTables.Add(Pivot_TableComboBox.Text);
                    channelGraph.Add(n);
                }
            }
        }

        private void Unpivot_AddToChannelButton_Click(object sender, EventArgs e)
        {
            try
            {
                System.Console.WriteLine(schemaHistory.Count);
                Scheme s = schemaHistory[schemaHistory.Count - 1].getScheme(Unpivot_TableComboBox.Text);

            }
            catch
            {
                MessageBox.Show("Could not find table \"" + Pivot_TableComboBox.Text + "\" in current schema");
                return;
            }
            List<String> table = new List<String>(1);
            List<String> attr = new List<String>(1);
            List<String> value = new List<String>(1);
            table.Add(Unpivot_TableComboBox.Text);
            attr.Add(Unpivot_AttrColComboBox.Text);
            value.Add(Unpivot_ValueColComboBox.Text);
            Unpivot t = new Unpivot(table, attr, value);
            channel.AddToEnd(t);
            if (channelModified())
            {
                foreach (String s in table)
                {
                    ChannelGraphNode n = new ChannelGraphNode("Unpivot");
                    n.inTableRev = schemaHistory.Count - 1;
                    n.inTables.Add(Unpivot_TableComboBox.Text);
                    n.outTableRev = schemaHistory.Count;
                    n.outTables.Add(Unpivot_TableComboBox.Text);
                    channelGraph.Add(n);
                }
            }
        }

        private void Audit_AddToChannelButton_Click(object sender, EventArgs e)
        {
            try
            {
                Schema cs = schemaHistory[schemaHistory.Count - 1];
                Scheme s = cs.getScheme(Audit_TableComboBox.Text);
            }
            catch
            {
                MessageBox.Show("Invalid Table Name");
                return;
            }
            List<String> tables = new List<String>();
            tables.Add(Audit_TableComboBox.Text);
            Transform t = new Audit(tables, "Added", "Deleted");
            channel.AddToEnd(t);

            if (channelModified())
            {
                foreach (String s in tables)
                {
                    ChannelGraphNode n = new ChannelGraphNode("Audit");
                    n.inTableRev = schemaHistory.Count - 1;
                    n.inTables.Add(s);
                    n.outTableRev = schemaHistory.Count;
                    n.outTables.Add(s);
                    channelGraph.Add(n);
                }
            }

        }

        private void Adorn_AddToChannelButton_Click(object sender, EventArgs e)
        {
            if (Adorn_newColumnTextBox.Text == "")
            {
                MessageBox.Show("Transform not added: New Column name must not be blank.");
                return;
            }
            List<String> tables = new List<String>();
            foreach (String s in Adorn_TablesCheckedListBox.CheckedItems)
                tables.Add(s);
            String newColumnName = Adorn_newColumnTextBox.Text;
            if (tables.Count == 0)
            {
                MessageBox.Show("Transform not added: At least one table must be selected.");
                return;
            }
            Transform t = null;
            switch (Adorn_FunctionComboBox.Text)
            {
                case "Current User":
                    t = new Adorn(tables, newColumnName, new CurrentUser(), Adorn_InsertOnlyCheckBox.Checked);
                    break;
                case "Current Machine":
                    t = new Adorn(tables, newColumnName, new CurrentMachine(), Adorn_InsertOnlyCheckBox.Checked);
                    break;
                case "Current Time":
                    t = new Adorn(tables, newColumnName, new CurrentTime(), Adorn_InsertOnlyCheckBox.Checked);
                    break;
                default:
                    MessageBox.Show("Invalid function selected.");
                    return;
            }
            channel.AddToEnd(t);
            if (channelModified())
            {
                foreach (String s in tables)
                {
                    ChannelGraphNode n = new ChannelGraphNode("Adorn");
                    n.inTableRev = schemaHistory.Count - 1;
                    n.inTables.Add(s);
                    n.outTableRev = schemaHistory.Count;
                    n.outTables.Add(s);
                    channelGraph.Add(n);
                }
            }

        }


        //     Helper methods
        private bool channelModified()
        {
            //update the form elements that depend on the current channel
            //update the schema revision history box

            //channel doesn't like being run more than once.
            channel = GuavaData.Channel.FromXDocument(channel.ToXDocument());
            Transaction t = initialSchema.Transaction;
            //channel.PoseTransactionWithEmptyProvider(t);// use this for debugging...
            
            try
            {
                channel.PoseTransactionWithEmptyProvider(t);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Channel not modified: " + ex.Message);
                channel.RemoveLastTransform();
                return false;
            }

            ImportChannelButton.Enabled = false;
            schemaHistory.Add(Schema.SchemaFromGuavaTransaction(t));

            int i = 0;
            schemaRevHistoryComboBox.Items.Clear();
            foreach (GuavaData.Schema s in schemaHistory)
            {
                if (i == 0)
                    schemaRevHistoryComboBox.Items.Add("Input Schema");
                else
                    schemaRevHistoryComboBox.Items.Add("Schema Rev " + (i + 1));
                i++;
            }
            schemaRevHistoryComboBox.SelectedIndex = schemaRevHistoryComboBox.Items.Count - 1;

            displayCurrentSchema();
            updateTransformEditor();
            return true;
        }

        private void displaySchema(GuavaData.Schema s)
        {
            //Takes a schema and displays it in "SchemaTreeView"
            SchemaTreeView.Nodes.Clear();
            foreach (TreeNode n in s.SchemaToTreeView(listViewCheckBox.Checked))
                SchemaTreeView.Nodes.Add(n);
            SchemaTreeView.ExpandAll();
        }

        public void displayCurrentSchema()
        {
            displaySchema(schemaHistory[schemaHistory.Count - 1]);
            currentlyDisplayedSchRev = schemaHistory.Count - 1;
        }

        private void updateTransformEditor()
        {

            //Updates the transform editor components with the latest schema. For example,
            //it populates drop down menus with table names so the user doesn't have to type them.

            if (getTestDataButton.Enabled)
            {
                testDataTableComboBox.Items.Clear();
                testDataTableComboBox.Text = "";
                foreach (Scheme s in schemaHistory[currentlyDisplayedSchRev].tables)
                    testDataTableComboBox.Items.Add(s.tableName);
            }

            //Set up page 1 - VPartition
            VPartition_KeepCols1CheckedListBox.Items.Clear();
            VPartition_KeepCols2CheckedListBox.Items.Clear();
            VPartition_TableComboBox.Items.Clear();
            VPartition_TableComboBox.Text = "";
            VPartition_t1NameTextBox.Text = "";
            VPartition_t2NameTextBox.Text = "";
            foreach (GuavaData.Scheme t in schemaHistory[currentlyDisplayedSchRev].tables)
                VPartition_TableComboBox.Items.Add(t.tableName);

            //Set up page 2 - VMerge
            VMerge_Table1ComboBox.Items.Clear();
            VMerge_Table2ComboBox.Items.Clear();
            VMerge_Table1ComboBox.Text = "";
            VMerge_Table2ComboBox.Text = "";
            foreach (GuavaData.Scheme t in schemaHistory[currentlyDisplayedSchRev].tables)
            {
                VMerge_Table1ComboBox.Items.Add(t.tableName);
                VMerge_Table2ComboBox.Items.Add(t.tableName);
            }

            //Set up page 3 - HPartition
            HPartition_TableComboBox.Items.Clear();
            HPartition_TableComboBox.Text = "";
            HPartition_BaseColValuesListBox.Items.Clear();
            HPartition_BaseColumnComboBox.Items.Clear();
            HPartition_BaseColumnComboBox.Text = "";
            foreach (GuavaData.Scheme t in schemaHistory[currentlyDisplayedSchRev].tables)
                HPartition_TableComboBox.Items.Add(t.tableName);

            //Set up page 4 - HMerge
            HMerge_ToMergeListBox.Items.Clear();
            HMerge_ResultTableNameTextBox.Text = "";
            foreach (GuavaData.Scheme t in schemaHistory[currentlyDisplayedSchRev].tables)
                HMerge_ToMergeListBox.Items.Add(t.tableName);

            //Set up page 5 - Audit
            Audit_TableComboBox.Items.Clear();
            Audit_TableComboBox.Text = "";
            foreach (GuavaData.Scheme s in schemaHistory[currentlyDisplayedSchRev].tables)
                Audit_TableComboBox.Items.Add(s.tableName);
            

            //Set up page 6 - Apply

            //Set up page 7 - Pivot
            Pivot_TableComboBox.Items.Clear();
            Pivot_TableComboBox.Text = "";
            foreach (GuavaData.Scheme s in schemaHistory[currentlyDisplayedSchRev].tables)
                Pivot_TableComboBox.Items.Add(s.tableName);

            //Set up page 8 - Unpivot
            Unpivot_TableComboBox.Items.Clear();
            Unpivot_TableComboBox.Text = "";
            foreach (GuavaData.Scheme s in schemaHistory[currentlyDisplayedSchRev].tables)
                Unpivot_TableComboBox.Items.Add(s.tableName);

            //Set up page 9 - Adorn
            Adorn_TablesCheckedListBox.Items.Clear();
            foreach (GuavaData.Scheme s in schemaHistory[currentlyDisplayedSchRev].tables)
                Adorn_TablesCheckedListBox.Items.Add(s.tableName);
            Adorn_FunctionComboBox.Items.Clear();
            Adorn_FunctionComboBox.Items.Add("Current Time");
            Adorn_FunctionComboBox.Items.Add("Current User");
            Adorn_FunctionComboBox.Items.Add("Current Machine");
        }

        public XDocument SchemaToGtree(GuavaData.Schema s)
        {
            List<GuavaData.Scheme> roots = new List<Scheme>();
            foreach (GuavaData.Scheme table in s.tables)
            {
                if (table.parents.Count == 0)
                {
                    roots.Add(table);
                }
            }

            XElement x = new XElement("GTree");
            foreach (GuavaData.Scheme table in roots)
            {
                x.Add(schemeToXml(table, s));
            }
            return new XDocument(x);
        }

        private XElement schemeToXml(GuavaData.Scheme s, GuavaData.Schema sch)
        {
            String launchType = "NA";
            String tabName = s.tableName;
            //tabName = tabName.Trim();
            tabName = tabName.Replace(' ', '_');
            if (s.parents.Count > 0 && s.fkColumns.Equals(s.pkColumns)) launchType = "Single";
            XElement x = new XElement(tabName, new XAttribute("Control", ""),
                new XAttribute("ControlType", "Entity"), new XAttribute("Width", ""),
                new XAttribute("Height", ""), new XAttribute("X", ""), new XAttribute("Y", ""),
                new XAttribute("Text", ""), new XAttribute("launchType", launchType),
                new XAttribute("print", ""), new XAttribute("condition", ""), new XAttribute("Type", ""));

            foreach (GuavaData.Column col in s.columns)
            {
                String domain = col.dom.DBType;
                XElement attr = new XElement(col.Name, new XAttribute("Control", ""),
                new XAttribute("ControlType", "Attribute"), new XAttribute("Width", ""),
                new XAttribute("Height", ""), new XAttribute("X", ""), new XAttribute("Y", ""),
                new XAttribute("Text", ""), new XAttribute("launchType", launchType),
                new XAttribute("print", ""), new XAttribute("condition", ""), new XAttribute("Type", domain));
                if (col.dom is GuavaData.Domain.Enumerated)
                {
                    attr.Add(col.dom.ToXElement());
                }
                x.Add(attr);
            }

            foreach (string table in s.children)
            {
                foreach (GuavaData.Scheme tab in sch.tables)
                {
                    if (tab.tableName.Equals(table))
                    {
                        x.Add(schemeToXml(tab, sch));
                        break;
                    }
                }

            }
            return x;
        }

        private void expGtree_Click(object sender, EventArgs e)
        {
            saveFileDialog1.ShowDialog();
            String path = saveFileDialog1.FileName;
            if (path != null && path != "")
            {
                XDocument x = SchemaToGtree(schemaHistory[schemaHistory.Count - 1]);
                x.Save(path);
            }
        }
       

    }
}
